﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class HexGrid
{
    public struct Cell
    {
        public int X { get; private set; }
        public int Y { get; private set; }
        public int Layers { get; private set; }
 
        private object[] _objs;
 
        public Cell(int x,int y,int layers)
        {
            X = x;
            Y = y;
            Layers = layers;
            _objs = new object[layers];
        }
 
        public void SetObj(int layer,object obj)
        {
            _objs[layer] = obj;
        }
 
        public object GetObj(int layer)
        {
            return _objs[layer];
        }
    }
 
    public enum Dir
    {
        Top,RightTop,RightBottom,Bottom,LeftBottom,LeftTop
    }
 
    private static readonly float _rate = Mathf.Sqrt(3) * 0.5f;
 
    public int Width { get; private set; }
    public int Height { get; private set; }
    public Vector3 Origin { get; set; } = Vector3.zero;
 
    private float _edgeLen = 1;
    private float _halfHeight = _rate;
    public float EdgeLength {
        get { return _edgeLen; }
        set {
            _edgeLen = value;
            _halfHeight = _edgeLen * _rate;
        }
    }
 
    private Cell[,] _grid;
 
    public HexGrid(int w,int h,int layers)
    {
        _grid = new Cell[w,h];
        for (int x = 0; x < w; x++)
        {
            for (int y = 0; y < h; y++)
            {
                _grid[x, y] = new Cell(x, y, layers);
            }
        }
 
        Width = w;
        Height = h;
    }
 
    public Cell GetCell(int x,int y)
    {
        return _grid[x, y];
    }
 
    public Vector3 GetWorldPos(int x,int y)
    {
        float wx = x * _edgeLen *1.5f;
        float wz = (y * 2 + x % 2) * _halfHeight;
        return Origin + new Vector3(wx, 0, wz);
    }
 
    public Vector2Int GetGridPos(float worldX,float worldY)
    {
        var tx = (worldX - Origin.x) / (_edgeLen * 1.5f);
        int cx = Mathf.RoundToInt(tx);
        var ty = ((worldY - Origin.z) / _halfHeight - cx%2) / 2f;
        int cy = Mathf.RoundToInt(ty);
        return new Vector2Int(cx, cy);
    }
 
    public Vector2Int GetNear(int x,int y,Dir dir)
    {
        bool up = x % 2 == 1;
        int nx, ny;
        nx = x;ny = y;
        switch (dir)
        {
            case Dir.Top:
                ny += 1;
                break;
            case Dir.RightTop:
                nx += 1;
                if(up)
                    ny += 1;
                break;
            case Dir.RightBottom:
                nx += 1;
                if (!up)
                    ny -= 1;
                break;
            case Dir.Bottom:
                ny -= 1;
                break;
            case Dir.LeftBottom:
                nx -= 1;
                if (!up)
                    ny -= 1;
                break;
            case Dir.LeftTop:
                nx -= 1;
                if (up)
                    ny += 1;
                break;
            default:
                break;
        }
 
        return new Vector2Int(nx, ny);
    }
 
    
    public bool IsInRange(int x,int y)
    {
        return x >= 0 && x < Width && y >= 0 && y < Height;
    }
    
}